﻿//------------------------------------------------------------------------------
// <copyright company="Tunynet">
//     Copyright (c) Tunynet Inc.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using PanGu;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace Tunynet.Search
{
    /// <summary>
    /// 关键字过滤/解析工具类
    /// </summary>
    public class ClauseScrubber
    {
        private static readonly string[] LuceneKeywords = new string[] { @"\", "+", "-", "(", ")", ":", "^", "[", "]", "{", "}", "~", "*", "?", "!", "\"", "'" };

        /// <summary>
        /// 去除Lucene关键字
        /// </summary>
        public static string LuceneKeywordsScrub(string str)
        {
            str = Remove(str, LuceneKeywords);
            if (str != null)
                str = str.Trim();

            return str;
        }

        /// <summary>
        /// 检查字符串中是否以字母(a-z,A-Z)或数字开头
        /// </summary>
        /// <param name="str">检查的字符串</param>
        /// <returns>如果包含字母或数字返回true,否则返回false</returns>
        public static bool StartsWithLetterOrDigit(string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;

            bool result = false;
            char startChar = str[0];
            switch (Char.GetUnicodeCategory(startChar))
            {
                case UnicodeCategory.DecimalDigitNumber:
                case UnicodeCategory.LowercaseLetter:
                case UnicodeCategory.UppercaseLetter:
                    result = true;
                    break;
            }
            return result;
        }

        /// <summary>
        /// 为PhraseQuery切分关键词
        /// </summary>
        /// <param name="keywords">待切分关键词</param>
        /// <returns></returns>
        public static string[] SegmentForPhraseQuery(string keywords)
        {
            ICollection<WordInfo> words = SegmentToWordInfos(keywords);
            return words.Select(n => n.Word).ToArray();
        }

        /// <summary>
        /// 根据文章标题智能解析关键字(或标签)
        /// </summary>
        /// <param name="title"></param>
        /// <returns></returns>
        public static string[] TitleToKeywords(string title)
        {
            ICollection<WordInfo> words = TitleToKeywordWordInfos(title);
            return words.Select(n => n.Word).Where(n => n.Length > 1).Distinct().ToArray();
        }

        #region Help Methods

        private static string Remove(string str, string[] removeStrings)
        {
            if (string.IsNullOrEmpty(str) || removeStrings == null)
                return str;

            string[] arraySplit = str.Split(removeStrings, StringSplitOptions.RemoveEmptyEntries);

            return string.Join("", arraySplit);
        }

        /// <summary>
        /// 把一个语句划分成多个词
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private static ICollection<WordInfo> SegmentToWordInfos(string str)
        {
            PanGu.Segment segment = new Segment();

            PanGu.Match.MatchOptions matchOptions = new PanGu.Match.MatchOptions();

            //中文人名识别
            matchOptions.ChineseNameIdentify = false;
            //词频优先
            matchOptions.FrequencyFirst = false;
            //多元分词
            matchOptions.MultiDimensionality = true;
            //英文多元分词，这个开关，会将英文中的字母和数字分开
            matchOptions.EnglishMultiDimensionality = false;
            //过滤停用词
            matchOptions.FilterStopWords = true;
            //忽略空格、回车、Tab
            matchOptions.IgnoreSpace = true;
            //强制一元分词
            matchOptions.ForceSingleWord = false;
            //繁体中文开关
            matchOptions.TraditionalChineseEnabled = false;
            //同时输出简体和繁体
            matchOptions.OutputSimplifiedTraditional = false;
            //未登录词识别
            matchOptions.UnknownWordIdentify = false;
            //过滤英文，这个选项只有在过滤停用词选项生效时才有效
            matchOptions.FilterEnglish = false;
            //过滤数字，这个选项只有在过滤停用词选项生效时才有效
            matchOptions.FilterNumeric = false;
            //忽略英文大小写
            matchOptions.IgnoreCapital = true;
            //英文分词
            matchOptions.EnglishSegment = false;
            //同义词输出  （同义词输出功能一般用于对搜索字符串的分词，不建议在索引时使用）
            matchOptions.SynonymOutput = false;
            //通配符匹配输出 （）
            matchOptions.WildcardOutput = false;
            //对通配符匹配的结果分词
            matchOptions.WildcardSegment = false;

            PanGu.Match.MatchParameter matchParameter = new PanGu.Match.MatchParameter();
            //未登录词权值
            matchParameter.UnknowRank = 1;
            //最匹配词权值
            matchParameter.BestRank = 5;
            //次匹配词权值
            matchParameter.SecRank = 3;
            //再次匹配词权值
            matchParameter.ThirdRank = 2;
            //强行输出的单字的权值
            matchParameter.SingleRank = 1;
            //数字的权值
            matchParameter.NumericRank = 1;
            //英文词汇权值
            matchParameter.EnglishRank = 5;
            //英文词汇小写的权值
            matchParameter.EnglishLowerRank = 3;
            //英文词汇词根的权值
            matchParameter.EnglishStemRank = 2;
            //符号的权值
            matchParameter.SymbolRank = 1;
            //强制同时输出简繁汉字时，非原来文本的汉字输出权值。 比如原来文本是简体，这里就是输出的繁体字的权值，反之亦然。
            matchParameter.SimplifiedTraditionalRank = 1;
            //同义词权值
            matchParameter.SynonymRank = 1;
            //通配符匹配结果的权值
            matchParameter.WildcardRank = 1;
            //过滤英文选项生效时，过滤大于这个长度的英文
            matchParameter.FilterEnglishLength = 0;
            //过滤数字选项生效时，过滤大于这个长度的数字
            matchParameter.FilterNumericLength = 0;
            //用户自定义规则的配件文件名
            matchParameter.CustomRuleAssemblyFileName = string.Empty;
            //用户自定义规则的类的完整名，即带名字空间的名称
            matchParameter.CustomRuleFullClassName = string.Empty;
            //冗余度
            matchParameter.Redundancy = 2;

            return segment.DoSegment(str, matchOptions, matchParameter);
        }

        /// <summary>
        /// 根据文章标题智能解析关键字(或标签)
        /// </summary>
        /// <param name="title"></param>
        /// <returns></returns>
        private static ICollection<WordInfo> TitleToKeywordWordInfos(string title)
        {
            PanGu.Segment segment = new Segment();

            PanGu.Match.MatchOptions matchOptions = new PanGu.Match.MatchOptions();

            //中文人名识别
            matchOptions.ChineseNameIdentify = false;
            //词频优先
            matchOptions.FrequencyFirst = false;
            //多元分词
            matchOptions.MultiDimensionality = false;
            //英文多元分词，这个开关，会将英文中的字母和数字分开
            matchOptions.EnglishMultiDimensionality = false;
            //过滤停用词
            matchOptions.FilterStopWords = true;
            //忽略空格、回车、Tab
            matchOptions.IgnoreSpace = true;
            //强制一元分词
            matchOptions.ForceSingleWord = false;
            //繁体中文开关
            matchOptions.TraditionalChineseEnabled = false;
            //同时输出简体和繁体
            matchOptions.OutputSimplifiedTraditional = false;
            //未登录词识别
            matchOptions.UnknownWordIdentify = false;
            //过滤英文，这个选项只有在过滤停用词选项生效时才有效
            matchOptions.FilterEnglish = true;
            //过滤数字，这个选项只有在过滤停用词选项生效时才有效
            matchOptions.FilterNumeric = true;
            //忽略英文大小写
            matchOptions.IgnoreCapital = false;
            //英文分词
            matchOptions.EnglishSegment = false;
            //同义词输出  （同义词输出功能一般用于对搜索字符串的分词，不建议在索引时使用）
            matchOptions.SynonymOutput = false;
            //通配符匹配输出 （）
            matchOptions.WildcardOutput = false;
            //对通配符匹配的结果分词
            matchOptions.WildcardSegment = false;

            PanGu.Match.MatchParameter matchParameter = new PanGu.Match.MatchParameter();
            //未登录词权值
            matchParameter.UnknowRank = 1;
            //最匹配词权值
            matchParameter.BestRank = 5;
            //次匹配词权值
            matchParameter.SecRank = 3;
            //再次匹配词权值
            matchParameter.ThirdRank = 2;
            //强行输出的单字的权值
            matchParameter.SingleRank = 1;
            //数字的权值
            matchParameter.NumericRank = 1;
            //英文词汇权值
            matchParameter.EnglishRank = 5;
            //英文词汇小写的权值
            matchParameter.EnglishLowerRank = 3;
            //英文词汇词根的权值
            matchParameter.EnglishStemRank = 2;
            //符号的权值
            matchParameter.SymbolRank = 1;
            //强制同时输出简繁汉字时，非原来文本的汉字输出权值。 比如原来文本是简体，这里就是输出的繁体字的权值，反之亦然。
            matchParameter.SimplifiedTraditionalRank = 1;
            //同义词权值
            matchParameter.SynonymRank = 1;
            //通配符匹配结果的权值
            matchParameter.WildcardRank = 1;
            //过滤英文选项生效时，过滤大于这个长度的英文
            matchParameter.FilterEnglishLength = 0;
            //过滤数字选项生效时，过滤大于这个长度的数字
            matchParameter.FilterNumericLength = 0;
            //用户自定义规则的配件文件名
            matchParameter.CustomRuleAssemblyFileName = string.Empty;
            //用户自定义规则的类的完整名，即带名字空间的名称
            matchParameter.CustomRuleFullClassName = string.Empty;
            //冗余度
            matchParameter.Redundancy = 0;

            return segment.DoSegment(title, matchOptions, matchParameter);
        }

        #endregion Help Methods
    }
}